using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace RfidApiLib
{
    public class RfidApi
    {
        public byte PortType = 0;
        ///<summary>
        ///端口名称(COM1,COM2...COM4...)
        ///</summary>

        //public string Port = "COM2:";
        public int BaudRate = 9600;
        public byte ByteSize = 8; //4-8
        public byte Parity = 0;   //0-4=no,odd,even,mark,space
        public byte StopBits = 0;   //0,1,2 = 1, 1.5, 2
        public int ReadTimeout = 1000;
        public bool Opened = false;

        private System.IO.Ports.SerialPort hComm = new System.IO.Ports.SerialPort();

        ///<summary>
        ///建立与串口的连接
        ///</summary>
        public int OpenCommPort(string port)
        {
            hComm.BaudRate = BaudRate;
            hComm.PortName = port;
            try
            {
                hComm.Open();
                Opened = true;
            }
            catch
            {
                Opened = false;
            }
            PortType = 0;
            return 0;
        }
        ///<summary>
        ///关闭串口,结束通讯
        ///</summary>
        public void CloseCommPort()
        {
            if (hComm.IsOpen)
                hComm.Close();
        }
        ///<summary>
        ///读取串口返回的数据
        ///</summary>
        ///<param name="NumBytes">数据长度</param>
        private int Read(ref byte[] bytData, int NumBytes)
        {
            int BytesRead = 0;

            if (hComm.IsOpen)
            {
                for (int nTemp = 0; nTemp < 10; nTemp++)
                {
                    BytesRead = hComm.Read(bytData, 0, NumBytes);
                    Console.WriteLine("已读字节数------>"+ BytesRead.ToString());
                    if (BytesRead > 0)
                        break;
                    else
                    {
                        System.Threading.Thread.Sleep(10);
                    }
                }
                return BytesRead;
            }
            else
            {
                return -1;
            }
        }

        ///<summary>
        ///向串口写数据
        ///</summary>
        ///<param name="WriteBytes">数据数组</param>
        private int Write(byte[] WriteBytes, int intSize)
        {
            int BytesWritten = 0;
            if (hComm.IsOpen)
            {
                try
                {
                    hComm.Write(WriteBytes, 0, intSize);
                    BytesWritten = intSize;
                }
                catch
                {
                    BytesWritten = 0;
                }
            }
            else
            {
                return -1;
            }
            return BytesWritten;
        }

        ///<summary>
        ///清除接收缓冲区
        ///</summary>
        ///<returns></returns>
        private void ClearReceiveBuf()
        {
            if (hComm.IsOpen)
            {
                hComm.DiscardInBuffer();
            }
        }

        ///<summary>
        ///清除发送缓冲区
        ///</summary>
        private void ClearSendBuf()
        {
            if (hComm.IsOpen)
            {
                hComm.DiscardOutBuffer();
            }
        }

        /// <summary>
        /// TCP PART
        /// </summary>
        public Socket sock;
        public int TcpConnectReader(string ip, int port)
        {
            IPAddress addr = IPAddress.Parse(ip);
            IPEndPoint reader_end = new IPEndPoint(addr, port);
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                sock.Connect(reader_end);
            }
            catch (Exception)
            {
                return 1;
            }
            if (sock.Connected)
            {
                PortType = 1;
                return 0;
            }
            else
                return 1;

        }

        public int TcpCloseConnect()
        {
            if (sock != null)
                sock.Close();
            return 0;
        }

        private int TcpSend(byte[] send_buf, int len)
        {
            if (sock.Connected == false)
                return 1;

            if (sock.Available > 0)
            {
                byte[] byClearBuf = new byte[sock.Available];
                sock.Receive(byClearBuf);                
            }
            int status = sock.Send(send_buf, len, 0);
            return status;
        }

        private int TcpReceive(ref byte[] rcv_buf, int len)
        {
            if (sock.Connected == false)
                return 1;
            int l = sock.Receive(rcv_buf, len, 0);
            return l;

        }

        private int SendAndRcv(byte[] send_buf, int intSize, ref byte[] rcv_buf)
        {
            int len;
            byte[] sof_buf = new byte[3];
            byte cc = 0;
            for (int i = 0; i < intSize - 1; i++)
            {
                cc += send_buf[i];
            }
            cc = (byte)(~cc + 1);
            send_buf[intSize - 1] = cc;
            if (PortType == 0)
            {
                this.ClearSendBuf();
                this.ClearReceiveBuf();

                if (this.Write(send_buf, intSize) != intSize)
                    return 1;

                Thread.Sleep(40);
                if (hComm.BytesToRead == 0) return 4;
                Console.WriteLine("可读字节数--->"+hComm.BytesToRead.ToString());
                if (this.Read(ref sof_buf, 3) == 3)
                {
                    if (sof_buf[0] != 0x0B)
                        return 2;
                    len = sof_buf[2];
                    if (this.Read(ref rcv_buf, len) != len)
                        return 3;
                    return 0;
                }
                else
                    return 4;
            }
            else
            {
                if (this.TcpSend(send_buf, intSize) != intSize)
                    return 1;
                if (this.TcpReceive(ref sof_buf, 3) == 3)
                {
                    if (sof_buf[0] != 0x0B)
                        return 2;
                    len = sof_buf[2];
                    if (this.TcpReceive(ref rcv_buf, len) != len)
                        return 3;
                    return 0;
                }
                else
                    return 4;
            }

        }

        private int GetTagData(ref byte[,] tag_data,ref byte tag_cnt)
        {
            int status;
            byte cnt = 0;
            byte sum0 = 0;
            byte[] SendBuf = new byte[6] { 0x0A, 0xFF, 0x03, 0x40, 0x08, 0xAC };
            byte[] RcvBuf = new byte[128];
            do
            {
                status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
                if (status == 0)
                {
                    cnt = RcvBuf[1];
                    if (cnt <= 0)
                        break;
                    for (int i = 0; i < cnt; i++)
                    {
                        for (int j = 0; j < 12; j++)
                        {
                            tag_data[sum0, j] = RcvBuf[i * 14 + j + 4];
                        }
                        sum0++;
                    }
                }
            } while (sum0 < tag_cnt);//

            tag_cnt = sum0;
            return status;
        }

        public int ClearIdBuf()
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x44, 0xB1 };
            byte[] RcvBuf = new byte[6];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            return status;
        }

        public int GetFirmwareVersion(ref byte v1, ref byte v2)
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x22, 0x00 };
            byte[] RcvBuf = new byte[8];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            if (status != 0)
                return status;

            v1 = RcvBuf[1];
            v2 = RcvBuf[2];
            return RcvBuf[0];
        }

        public int GetDeviceSN(ref string strSerialNo)
        {
            int status;
            byte[] SendBuf = new byte[6] { 0x0A, 0xFF, 0x03, 0x24, 0x30, 0x00 };
            byte[] RcvBuf = new byte[32];
            byte[] bySNData = new byte[12];
            for (int iIndex = 0; iIndex < 12; iIndex++)
            {
                SendBuf[4] = (byte)(0x30 + iIndex);
                status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
                if (status != 0)
                    return status;
                bySNData[iIndex] = RcvBuf[1];
            }
            return RcvBuf[0];
        }

        public int SetRf(byte power, byte freq_type)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x04, 0x25, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];

            SendBuf[4] = power;
            SendBuf[5] = freq_type;

            status = this.SendAndRcv(SendBuf, 7, ref RcvBuf);
            return status;
        }

        public int GetRf(ref byte power, ref byte freq_type)
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x26, 0x00 };
            byte[] RcvBuf = new byte[8];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            if (status != 0)
                return status;

            power = RcvBuf[1];
            freq_type = RcvBuf[2];
            return RcvBuf[0];
        }

        public int SetAnt(byte ant)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x03, 0x27, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];

            SendBuf[4] = ant;

            status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
            return status;

        }

        public int GetAnt(ref byte ant)
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x28, 0x00 };
            byte[] RcvBuf = new byte[8];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            if (status != 0)
                return status;
            ant = RcvBuf[1];
            return RcvBuf[0];
        }

        public int SetOutPort(byte port_num, byte level)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x04, 0x2D, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[8];

            SendBuf[4] = port_num;
            SendBuf[5] = level;
            status = this.SendAndRcv(SendBuf, 7, ref RcvBuf);
            return status;
        }

        public int IsoMultiTagIdentify(ref byte[,] tag_buf, ref byte tag_cnt)
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x60, 0x95 };
            byte[] RcvBuf = new byte[64];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            if (status == 0)
            {
                tag_cnt = RcvBuf[1];
                this.GetTagData(ref tag_buf,ref tag_cnt);
            }
            return status;
        }

        public int IsoRead(byte addr, ref byte[] value)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x03, 0x68, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[16];

            SendBuf[4] = addr;

            status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
            if (status != 0)
                return status;
            for (int i = 0; i < 8; i++)
                value[i] = RcvBuf[i + 2];
            return RcvBuf[0];
        }

        public int IsoWrite(byte addr, byte value)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x04, 0x62, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];

            SendBuf[4] = addr;
            SendBuf[5] = value;

            status = this.SendAndRcv(SendBuf, 7, ref RcvBuf);
            if (status != 0)
                return status;
            return RcvBuf[0];
        }

        public int IsoLock(byte addr)
        {
            int status;
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x03, 0x65, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];

            SendBuf[4] = addr;

            status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
            if (status != 0)
                return status;
            return RcvBuf[0];
        }

        //读取指定ID号的标签数据，每次读取指定地址开始的8字节数据
        public int IsoReadWithID(byte[] byTagID,byte byAddress,ref byte[] byLabelData,ref byte byAntenna)	
        {
	        byte[] SendBuf = {0x0A,0xFF,11,0x63,0,0,0,0,0,0,0,0,0,0};
            for (int i = 0; i < 8; i++)
                SendBuf[4 + i] = byTagID[i];
	        SendBuf[12]=byAddress;
            byte[] Response = new byte[256];
	        int fSuccess;

	        fSuccess = this.SendAndRcv(SendBuf,14,ref Response);
	        if(fSuccess != 0)
		        return fSuccess;
	        if (Response[0]!=0x00)
		        return (2100+Response[3]);
            byAntenna = Response[4];
	        for (int i=0;i<8;i++)
                byLabelData[i] = Response[2 + i];
            byAntenna = Response[1];
            return fSuccess;
        }

        public int IsoWriteWithID(byte[] byTagID,byte byAddress,byte byValue) //向指定地址写入1字节内容
        {
	        byte[] SendBuf = {0x0A,0xFF,12,0x64,0,0,0,0,0,0,0,0,0,0,0};
            for (int i = 0; i < 8; i++)
                SendBuf[4 + i] = byTagID[i];

            SendBuf[12] = byAddress;
	        SendBuf[13] = byValue;
            byte[] Response = new byte[256];
	        int fSuccess;

            fSuccess = this.SendAndRcv(SendBuf, 15, ref Response);
	        if (Response[3]!=0x00)
		        return (2100+Response[3]);
	        return fSuccess;
        }

        public int EpcMultiTagIdentify(ref byte[,] tag_buf, ref byte tag_cnt, ref byte tag_flag)
        {
            int status;
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x80, 0x95 };
            byte[] RcvBuf = new byte[64];
            status = this.SendAndRcv(SendBuf, 5, ref RcvBuf);
            if (status == 0)
            {
                tag_cnt = RcvBuf[1];
                tag_flag = RcvBuf[2];
                if(tag_cnt > 0)
                    this.GetTagData(ref tag_buf,ref tag_cnt);
            }
            return status;

        }

        public int EpcRead(byte membank, byte wordptr, byte wordcnt, ref byte[] value)
        {
            byte[] SendBuf = new byte[10] { 0x0A, 0xFF, 0x05, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[32];
            int ps;

            SendBuf[4] = membank;
            SendBuf[5] = wordptr;
            SendBuf[6] = wordcnt;
            ps = this.SendAndRcv(SendBuf, 8, ref RcvBuf);
            if (ps != 0)
                return ps;
            if (RcvBuf[0] == 0)
            {
                for (int i = 0; i < wordcnt * 2; i++)
                {
                    value[i] = RcvBuf[i + 2];
                }
            }
            return RcvBuf[0];
        }

        public int EpcWrite(byte membank, byte wordptr, ushort value)
        {
            byte[] SendBuf = new byte[10] { 0x0A, 0xFF, 0x06, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[32];
            int ps;
            SendBuf[4] = membank;
            SendBuf[5] = wordptr;
            SendBuf[6] = (byte)(value >> 8);
            SendBuf[7] = (byte)value;
            ps = this.SendAndRcv(SendBuf, 9, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int EpcLockTag(byte MemBank,byte LockLevel)
        {
            byte[] SendBuf = new byte[7] { 0x0A, 0xFF, 0x04, 0x82, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];
            int ps;

            SendBuf[4] = MemBank;
            SendBuf[5] = LockLevel;
            ps = this.SendAndRcv(SendBuf, 7, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int EpcInitEpc(byte bit_cnt)
        {
            byte[] SendBuf = new byte[6] { 0x0A, 0xFF, 0x03, 0x84, 0x00, 0x00 };
            byte[] RcvBuf = new byte[6];
            int ps;

            SendBuf[4] = bit_cnt;
            ps = this.SendAndRcv(SendBuf, 6, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int EpcSelectRead(byte membank, byte wordptr, byte wordcnt, ref byte[] value, ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[30] { 0x0A, 0xFF, 0x12, 0x8C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[32];
            int ps;

            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5 + iLoop] = EPC_CODE[iLoop];
            SendBuf[17] = membank;
            SendBuf[18] = wordptr;
            SendBuf[19] = wordcnt;
            ps = this.SendAndRcv(SendBuf, 21, ref RcvBuf);
            if (ps != 0)
                return ps;
            if (RcvBuf[0] == 0)
            {
                for (int i = 0; i < wordcnt * 2; i++)
                {
                    value[i] = RcvBuf[i + 2];
                }
            }
            return RcvBuf[0];
        }

        public int EpcSelectWrite(byte membank, byte wordptr, ushort value, ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[30] { 0x0A, 0xFF, 0x13, 0x8D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[32];
            int ps;

            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5 + iLoop] = EPC_CODE[iLoop];
            SendBuf[17] = membank;
            SendBuf[18] = wordptr;
            SendBuf[19] = (byte)(value >> 8);
            SendBuf[20] = (byte)value;
            ps = this.SendAndRcv(SendBuf, 22, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int EpcIdentifyStart()
        {
            int status;
            byte[] SendBuf = new byte[6] { 0x0A, 0xFF, 0x03, 0x8B, 0x01, 0x68 };
            byte[] RcvBuf = new byte[64];
            status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);

            return status;

        }

        public int Gen2SecLock(uint AccPassWord, byte Membank, byte Action,ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[30] { 0x0A, 0xFF, 0x16, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[256];
            int ps;
            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5 + iLoop] = EPC_CODE[iLoop];
            SendBuf[17] = (byte)((AccPassWord >> 24) & 0xFF);
            SendBuf[18] = (byte)((AccPassWord >> 16) & 0xFF);
            SendBuf[19] = (byte)((AccPassWord >> 8) & 0xFF);
            SendBuf[20] = (byte)(AccPassWord & 0xff);
            SendBuf[21] = Membank;
            SendBuf[22] = 0x03;
            SendBuf[23] = Action;
            ps = this.SendAndRcv(SendBuf, 25, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0]; 
        }

        public int Gen2SecRead(uint AccPassWord, byte Membank, byte WordAddr, byte WordCnt, ref byte[] value, ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[30] { 0x0A, 0xFF, 0x16, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[256];
            int ps;
            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5 + iLoop] = EPC_CODE[iLoop];
            SendBuf[17] = (byte)((AccPassWord >> 24) & 0xFF);
            SendBuf[18] = (byte)((AccPassWord >> 16) & 0xFF);
            SendBuf[19] = (byte)((AccPassWord >> 8) & 0xFF);
            SendBuf[20] = (byte)(AccPassWord & 0xff);
            SendBuf[21] = Membank;
            SendBuf[22] = WordAddr;
            SendBuf[23] = WordCnt;
            ps = this.SendAndRcv(SendBuf, 25, ref RcvBuf);
            if (ps != 0)
                return ps;
            if (RcvBuf[0] == 0)
            {
                for (int i = 0; i < WordCnt * 2; i++)
                {
                    value[i] = RcvBuf[i + 2];
                }
            }
            return RcvBuf[0];
        }

        public int Gen2SecWrite(uint AccPassWord, byte Membank, byte WordAddr, ushort Value, ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[30] { 0x0A, 0xFF, 0x17, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[256];
            int ps;
            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5 + iLoop] = EPC_CODE[iLoop];
            SendBuf[17] = (byte)((AccPassWord >> 24) & 0xFF);
            SendBuf[18] = (byte)((AccPassWord >> 16) & 0xFF);
            SendBuf[19] = (byte)((AccPassWord >> 8) & 0xFF);
            SendBuf[20] = (byte)(AccPassWord & 0xff);
            SendBuf[21] = Membank;
            SendBuf[22] = WordAddr;
            SendBuf[23] = (byte)((Value >> 8) & 0xFF);
            SendBuf[24] = (byte)(Value & 0xFF);
            ps = this.SendAndRcv(SendBuf, 26, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int Gen2KillTag(uint AccPassWord, ref byte[] EPC_CODE)
        {
            byte[] SendBuf = new byte[20] { 0x0A, 0xFF, 0x13, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] RcvBuf = new byte[256];
            int ps;
            for (int iLoop = 0; iLoop < 12; iLoop++)
                SendBuf[5] = EPC_CODE[iLoop];
            SendBuf[17] = (byte)((AccPassWord >> 24) & 0xFF);
            SendBuf[18] = (byte)((AccPassWord >> 16) & 0xFF);
            SendBuf[19] = (byte)((AccPassWord >> 8) & 0xFF);
            SendBuf[20] = (byte)AccPassWord;
            ps = this.SendAndRcv(SendBuf, 22, ref RcvBuf);
            if (ps != 0)
                return ps;
            return RcvBuf[0];
        }

        public int ResetReader()
        {
            byte[] SendBuf = new byte[5] { 0x0A, 0xFF, 0x02, 0x21, 0xd4 };
            byte[] RcvBuf = new byte[6];

            if (PortType == 0)
            {
                this.ClearSendBuf();
                this.ClearReceiveBuf();
                this.Write(SendBuf, 5);
                this.CloseCommPort();
            }
            else
            {
                this.TcpSend(SendBuf, 5);
                this.TcpCloseConnect();
            }
            return 0;
        }

        //*功能：识别标签EPC编码
        //*参数：无
        //*返回：标签EPC码字符串，以“，”分割多个标签EPC码（返回"NOT"表示没有卡，返回"ERR"表示读卡失败）
        public string NOTESEpcTagIdentify()
        {
            string strResult = "";
            byte[,] tagData = new byte[300, 12];
            byte tagCount = 0;
            byte tagFlag = 0;
            ClearIdBuf();
            int status = EpcMultiTagIdentify(ref tagData, ref tagCount, ref tagFlag);
            if (status != 0)
            {
                strResult = "ERR";
                return strResult;
            }
            if (tagCount > 0)
            {
                for (int i = 0; i < tagCount; i++)
                {
                    string strID = "";
                    for (int j = 0; j < 12; j++)
                        strID += string.Format("{0:X2}", tagData[i, j]);
                    strResult = strResult + strID + ",";
                }
                strResult = strResult.Substring(0, strResult.Length - 1);
            }
            else
                strResult = "NOT";
            return strResult;
        }

        //*功能：读取标签指定数据区的内容
        //*参数：membank-数据区编号，wordptr-读取数据起始字地址，wordcnt-读取数据字长度
        //*返回：读到的数据内容（返回"ERR"表示没有卡或读卡失败）
        public string NOTESEpcRead(int membank, int wordptr, int wordcnt)
        {
            string strResult = "";
            byte[] tagValue = new byte[wordcnt * 2 + 1];
            int status = 0;// EpcSelectRead((byte)membank, (byte)wordptr, (byte)wordcnt, ref tagValue);
            if (status == 0)
            {
                strResult = Encoding.GetEncoding("GB2312").GetString(tagValue);
                //for (int i = 0; i < wordcnt * 2; i++)
                //    strResult = strResult +  string.Format("{0:X2", tagValue[i]);
            }
            else
                strResult = "ERR";
            return strResult;
        }

        //*功能：向标签指定数据区写入数据
        //*参数：membank-数据区编号，wordptr-读取数据起始字地址，value-要写入的内容（4个十六进制数据，例：3132）
        //*返回：写卡状态，"OK"－写入成功，"ERR"-写入失败
        public string NOTESEpcWrite(int membank, int wordptr,int wordcnt, string strValue)
        {
            string strResult = "";
            byte[] byUserData = Encoding.GetEncoding("GB2312").GetBytes(strValue);

            for (int i = 0; i < wordcnt; i++)
            {
                ushort usData = (ushort)(byUserData[i * 2] * 256 + byUserData[i * 2 + 1]);
                for (int j = 0; j < 3; j++)
                {
                    int status = 0;// EpcSelectWrite((byte)membank, (byte)(wordptr + i), usData);
                    if (status == 0)
                    {
                        strResult = "OK";
                        break;
                    }
                    else
                        strResult = "ERR";
                    System.Threading.Thread.Sleep(200);
                }
                if (strResult == "ERR")
                    break;
            }
            return strResult;
        }

        /// <summary>
        /// 启动、停止、接收标签，四通道主动读卡方式专用
        /// </summary>
        /// <returns></returns>
        public int EpcIdentifyStop()
        {
            int status;
            byte[] SendBuf = new byte[6] { 0x0A, 0xFF, 0x03, 0x8B, 0x00, 0x69 };
            byte[] RcvBuf = new byte[64];
            status = this.SendAndRcv(SendBuf, 6, ref RcvBuf);

            return status;

        }

        public int ReciveTagData(ref byte[,] tag_data, ref byte tag_cnt)
        {
            byte cnt = 0;
            byte len = 0;
            byte sum0 = 0;

            byte[] RcvBuf = new byte[256];
            byte[] sof_buf = new byte[3];

            if (PortType == 0)
            {
                if (hComm.BytesToRead == 0) return 4;
                if (this.Read(ref sof_buf, 3) == 3)
                {
                    if (sof_buf[0] != 0x0B)
                        return 2;
                    len = sof_buf[2];
                    if (this.Read(ref RcvBuf, len) != len)
                        return 3;
                }
                else
                    return 4;
            }
            else
            {
                if (this.TcpReceive(ref sof_buf, 3) == 3)
                {
                    if (sof_buf[0] != 0x0B)
                        return 2;
                    len = sof_buf[2];
                    if (this.TcpReceive(ref RcvBuf, len) != len)
                        return 3;
                }
                else
                    return 4;
            }

            cnt = RcvBuf[1];

            for (int i = 0; i < cnt; i++)
            {
                for (int j = 0; j < 12; j++)
                {
                    tag_data[sum0, j] = RcvBuf[i * 14 + j + 4];
                }
                sum0++;
            }

            tag_cnt = sum0;
            return 0;
        }
    }
}
